Overall Corridor Analysis

Overview

The Olney transit corridor runs along Chew Av , and Olney Av between Locust Av and Front St. The corridor serves the routes 18, and 26. There are 49 total bus stops along the corridor. The corridor directly served 1.8984^{4} riders per day in 2019.

route_id direction_id pattern_id pattern_type n_trips mean_run
18 Eastbound E08X secondary 5 57.2
18 Eastbound E10 secondary 5 331.0
18 Eastbound E04 secondary 1 301.0
18 Eastbound E12RMS secondary 1 474.0
18 Eastbound E07XPI secondary 1 670.0
18 Eastbound E07X secondary 6 521.2
18 Eastbound E09 primary 1 631.0
18 Eastbound E06 primary 15 704.7
18 Eastbound E01 primary 87 935.1
18 Eastbound E03 primary 2 634.5
18 Westbound W4 primary 26 837.5
18 Westbound W1 primary 111 862.9
18 Westbound W3 primary 3 737.7
18 Westbound W2 primary 48 826.9
18 Westbound W5WMS primary 1 970.0
26 Eastbound E6CERO secondary 1 1,719.0
26 Eastbound E6CEPI secondary 2 1,811.5
26 Eastbound E5 primary 31 907.5
26 Eastbound E4 primary 17 778.4
26 Eastbound E2 primary 25 877.3
26 Eastbound E7FEL primary 5 747.8
26 Eastbound E1 primary 19 912.9
26 Eastbound E1PI primary 8 961.4
26 Eastbound E2PI primary 4 890.2
26 Eastbound E3 primary 3 879.7
26 Westbound W5 secondary 1 351.0
26 Westbound W9FEL secondary 1 427.0
26 Westbound W6 primary 30 872.1
26 Westbound W4 primary 26 837.5
26 Westbound W2 primary 48 826.9
26 Westbound W1 primary 111 862.9
26 Westbound W3 primary 3 737.7
26 Westbound W8FEL primary 1 940.0
26 Westbound W7FEL primary 2 933.0
route_id daily_ridership trips routes_served service_hours riders_per_hour on_off dwell_observed_mean dwell_predicted_mean dwell_hybrid_mean dwell_per_onoff onoff_per_trip onoff_per_tripstop avg_segment_speed avg_speed_10_pct avg_speed_25_pct avg_speed_75_pct avg_speed_90_pct
18 10,570 234 18 54.0 195.9 11,426.4 0 216.2 216.2 0.2 48.8 2.1 11.1 9.1 9.6 11.9 14.2
26 8,414 229 26 55.5 151.5 9,839.4 0 199.3 199.3 0.2 43.0 1.8 10.9 9.4 9.9 11.6 13.2
Total 18,984 463 18, 26 109.5 173.4 21,265.8 0 207.8 207.8 0.2 45.9 1.9 11.0 9.2 9.8 11.7 14.0

Weekday Ridership

The corridor moves 1.8984^{4} transit passengers per day. The peak hour for transit passenger movement on the corridor is 7. At the peak hour, the corridor serves 2407 riders.

Speed and Reliability

Speed and reliability are two of the most important aspects governing how attractive transit is to the customer.

There is, however, an important distinction between transit speed and transit reliability:

  • speed is how fast the vehicle is moving through the corridor
  • reliability is how consistent those speeds are, throughout a day or another period of time.

Oftentimes, qualitative research on transit finds that riders remember their worst trip much more vividly than their average (or even their best) trips. This is where reliability is key - providing customers with a consistent trip time is just as important as a fast trip time, because when they budget time for future trips, they have to be reasonably sure that the time budgeted will represent the majority of potential travel time outcomes.

Bus Speeds

Reliability

Travel Times

Corridor-level travel time is simply the amount of time it takes the bus to travel from one end of the corridor to another. In this case, it is show separated by route and by direction and is averaged for each hour.

Service Hours

Service hours are a measure of how much transit is operated on the corridor. It is simply the sum of all of the runtime on the corridor over a period of time. Service hours is a product of how much transit is provide, but it is also a product of the speed of operations on a corridor. Transit productivity is often measured in terms of service hours because it is the most direct input into the cost of running the service.

Sub-Corridor Analysis

Analytics

Interpretation

Subcorridor Daily Analytics

route_id daily_ridership trips routes_served service_hours riders_per_hour on_off dwell_observed_mean dwell_predicted_mean dwell_hybrid_mean dwell_per_onoff onoff_per_trip onoff_per_tripstop avg_segment_speed avg_speed_10_pct avg_speed_25_pct avg_speed_75_pct avg_speed_90_pct
18 6,826 235 18 19.8 345.1 3,896.5 0 83.7 83.7 0.2 16.6 1.5 12.0 9.6 10.3 12.6 14.5
26 4,955 226 26 20.1 246.8 2,067.1 0 71.2 71.2 0.1 9.2 0.9 11.1 9.6 10.3 11.9 13.2
Total 11,781 461 18, 26 39.9 295.6 5,963.6 0 77.6 77.6 0.2 12.9 1.2 11.6 9.6 10.3 12.1 14.0

Weekday Ridership

Speed and Reliability

Speed
Reliability

End-to-End Travel Time

## NULL

Analytics

Interpretation

Subcorridor Daily Analytics

route_id daily_ridership trips routes_served service_hours riders_per_hour on_off dwell_observed_mean dwell_predicted_mean dwell_hybrid_mean dwell_per_onoff onoff_per_trip onoff_per_tripstop avg_segment_speed avg_speed_10_pct avg_speed_25_pct avg_speed_75_pct avg_speed_90_pct
18 8,501 223 18 11.6 731.5 5,281.6 0 85.5 85.5 0.3 23.7 4.0 10.2 8.1 8.8 11.2 12.7
26 6,992 229 26 15.1 462.2 5,542.4 0 75.2 75.2 0.3 24.2 3.5 11.5 9.3 10.2 12.5 14.2
Total 15,493 452 18, 26 26.8 579.2 10,824.0 0 80.3 80.3 0.3 24.0 3.4 10.9 8.4 9.3 12.1 13.6

Weekday Ridership

Speed and Reliability

Speed
Reliability

End-to-End Travel Time

## NULL

Analytics

Interpretation

Subcorridor Daily Analytics

route_id daily_ridership trips routes_served service_hours riders_per_hour on_off dwell_observed_mean dwell_predicted_mean dwell_hybrid_mean dwell_per_onoff onoff_per_trip onoff_per_tripstop avg_segment_speed avg_speed_10_pct avg_speed_25_pct avg_speed_75_pct avg_speed_90_pct
18 5,970 222 18 13.4 444.4 2,034.2 0 52.3 52.3 0.2 9.2 1.5 10.5 8.2 8.9 11.3 14.0
26 4,896 229 26 14.2 345.8 2,224.6 0 53.7 53.7 0.2 9.7 1.4 10.0 8.2 8.9 10.8 12.5
Total 10,867 451 18, 26 27.6 393.8 4,258.8 0 53.0 53.0 0.2 9.4 1.4 10.3 8.2 8.9 10.9 13.2

Weekday Ridership

Speed and Reliability

Speed
Reliability

End-to-End Travel Time

## NULL

Sub-Corridor Comparison

plot_speed_corridor_comparison(comparison_df)

Stop Level Analysis

Stop Level Map

label_stops <- function(dat) {
  
  daily <- dat$daily_stop_analytics
  hourly <- dat$stop_route_hourly_analytics
    
  paste0( "Stop:", daily[[i]]$stop_name , "<br>",
          "Stop ID: ", daily$stop_id, "<br>",
          "Daily Boards", daily$total_ons, "<br>",
          "Daily Leaves", daily$total_ons, "<br>",
          "Maximum Hourly Dwell: ", hourly$avg_dwell_hybrid)
  
}

# map of stops that on the corridor
leaflet() %>%
  setView(lng = mean(full_stop_data$daily_stop_analytics[[1]]$stop_lon, na.rm=TRUE), 
          lat = mean(full_stop_data$daily_stop_analytics[[1]]$stop_lat, na.rm=TRUE), zoom = 14) %>% 
  addProviderTiles(providers$Stamen.Toner) %>% 
  addCircleMarkers(full_stop_data$daily_stop_analytics[[1]], 
                   lat = full_stop_data$daily_stop_analytics[[1]]$stop_lat, 
                   lng = full_stop_data$daily_stop_analytics[[1]]$stop_lon, 
                   radius = log((full_stop_data$daily_stop_analytics[[1]]$total_ons + 
                               (full_stop_data$daily_stop_analytics[[1]]$total_offs)))*2.55, 
                   color = "blue", 
                   popup = popupTable(full_stop_data$daily_stop_analytics[[1]]))
# also add chart/table of global averages for context of subcorridors

Daily Analytics by Stop Table

table_2 <- full_stop_data$daily_stop_analytics[[1]] %>% select(-c(avg_speed, stop_lat, stop_lon))
 
# kable(table_2, booktabs = TRUE, align = 'c',format.args = list(big.mark = ","),digits=1) %>%
#   kable_styling(latex_options = "scale_down")  %>%
#   row_spec(dim(table_1)[1], bold = T) %>% # format last row
#   column_spec(1, italic = T) %>%  # format first column
#   scroll_box(width = "100%", height = "300px")

reactable(table_2,
    filterable = TRUE,
    resizable = TRUE,
    columns = list(
    # route_id = colDef(
    #   sticky = "left",
    #   headerStyle = list(borderRight = "1px solid #eee")
    # ),
    # direction_id = colDef(
    #   sticky = "left",
    #   headerStyle = list(borderRight = "1px solid #eee")
    # ),
    # stop_id = colDef(
    #   sticky = "left",
    #   headerStyle = list(borderRight = "1px solid #eee")
    # ),
    # stop_name = colDef(
    #   sticky = "left",
    #   # Add a right border style to visually distinguish the sticky column
    #   style = list(borderRight = "1px solid #eee"),
    #   headerStyle = list(borderRight = "1px solid #eee")
    # ),
      #total_trips = colDef(aggregate = "max"),
      #avg_headway = colDef(aggregate = "mean", format = colFormat(digits = 1)),
      total_ons = colDef(aggregate = "sum", format = colFormat(digits = 0)),
      total_offs = colDef(aggregate = "sum", format = colFormat(digits = 0)),
      avg_load = colDef(format = colFormat(digits = 0)),
      avg_dwell_observed = colDef(format = colFormat(digits = 2)),
      avg_dwell_estimated = colDef(format = colFormat(digits = 2)),
      avg_dwell_hybrid = colDef(format = colFormat(digits = 2)),
      avg_dwell_per_pass_hybrid = colDef(format = colFormat(digits = 2))
    )
)

Daily Analytics by Stop/Route Table

  • User input to add/subtracts routes - i.e. pull from the route level data?
table_3 <- full_stop_data$stop_route_analytics[[1]] %>% select(route_id, direction_id, everything()) %>% select(-c(routes, avg_speed, stop_lat, stop_lon)) %>%  group_by(route_id, direction_id) %>% dplyr::arrange(route_id, direction_id, stop_lon)

reactable(
  table_3,
  #filterable = TRUE,
  groupBy = c("route_id", "direction_id"),
  pagination = FALSE, 
  resizable = TRUE,
  height = 500,
  columns = list(
    # route_id = colDef(
    #   sticky = "left",
    #   headerStyle = list(borderRight = "1px solid #eee")
    # ),
    # direction_id = colDef(
    #   sticky = "left",
    #   headerStyle = list(borderRight = "1px solid #eee")
    # ),
    # stop_id = colDef(
    #   sticky = "left",
    #   headerStyle = list(borderRight = "1px solid #eee")
    # ),
    # stop_name = colDef(
    #   sticky = "left",
    #   # Add a right border style to visually distinguish the sticky column
    #   style = list(borderRight = "1px solid #eee"),
    #   headerStyle = list(borderRight = "1px solid #eee")
    # ),
    total_trips = colDef(aggregate = "max"),
    avg_headway = colDef(aggregate = "mean", format = colFormat(digits = 1)),
    total_ons = colDef(aggregate = "sum", format = colFormat(digits = 1)),
    total_offs = colDef(aggregate = "sum", format = colFormat(digits = 1)),
    avg_load = colDef(aggregate = "mean", format = colFormat(digits = 1)),
    avg_dwell_observed = colDef(aggregate = "mean", format = colFormat(digits = 1)),
    avg_dwell_estimated = colDef(aggregate = "mean", format = colFormat(digits = 1)),
    avg_dwell_hybrid = colDef(aggregate = "mean", format = colFormat(digits = 1)),
    avg_dwell_per_pass_hybrid = colDef(aggregate = "mean", format = colFormat(digits = 1))
  ),
  defaultColDef = colDef(minWidth = 150)
)

Stop Profile by Route/Direction